<template>
	<view class="content">
		<view class="app-logo">
			<image src='../../static/logo.png'></image>
		</view>
		<view class="app-login">
			<view class="app-login-form-item">
				<view class="app-login-form-item-label">
					<image src='../../static/image/login/phone.png' class="app-login-form-item-label-icon"></image>
					<text class="app-login-form-item-label-text">手机号</text>
				</view>
				<view class="app-login-form-input">
					<input type="number" maxlength="11" v-model='loginInfo.mobile' placeholder="请输入手机号" />
				</view>
			</view>
			<view class="app-login-form-item">
				<view class="app-login-form-item-label">
					<image src='../../static/image/login/verificationCode.png' class="app-login-form-item-label-icon">
					</image>
					<text class="app-login-form-item-label-text">验证码</text>
				</view>
				<view class="app-login-form-input">
					<input type="number" maxlength="6" v-model="loginInfo.captcha" placeholder="请输入验证码" />
					<text v-if="countdownTime == COUNTDOWN_DURATION" @click='getVerificationCode'
						class="send-verification">发送验证码</text>
					<text v-else> {{Math.ceil(countdownTime/1000)}} s</text>
				</view>
			</view>
			<view class="user-agreement" :class="{agreementShake}" @animationend='closeShake'>
				<view class='radio' @click="agreeAgreement">
					<image v-if="agreementStatus" src="/static/image/public/checked.png" class="radio-img"></image>
				</view>
				<view>
					查看<text class="agreement" @click='jumpAgreement'>《用户服务协议》</text>
				</view>

			</view>
			<button class="submit-button" @click="userLogin">注册/登录</button>
		</view>

	</view>
</template>

<script lang="ts" setup>
	import { ref, reactive, shallowRef } from 'vue';
	import { onNavigationBarButtonTap, onBackPress, onShow, onHide } from '@dcloudio/uni-app';
	import { useShowToast } from "@/utils/tools";
	import { sendSmsVerificationCode } from '@/api/public';
	import { apiMobilelogin } from '@/api/user';

	// 定义验证码缓存时间戳Key的引用类型
	const VERIFICATION_CODE_CACHE_TIMESTAMP_KEY = shallowRef<string>("verificationCodeEndTimestamp");

	// 设置倒计时总时长（单位：毫秒）
	const COUNTDOWN_DURATION = 60000;

	// 倒计时剩余时间的引用类型
	const countdownTime = ref<number>(COUNTDOWN_DURATION);
	// 倒计时是否正在进行的布尔引用类型
	const countdownRuning = ref<boolean>(false);

	// 定义登录信息的响应式对象，包含手机号和验证码
	const loginInfo = reactive<{ mobile : string; captcha : string; }>({
		mobile: "",
		captcha: "888888",
	});

	/**
	 * 获取短信验证码并启动倒计时功能
	 * @async
	 */
	const getVerificationCode = async () => {
		if (!checkMobile()) {
			return;
		}

		// 检查用户是否同意用户服务协议
		if (!agreementStatus.value) {
			agreementShake.value = true;
			useShowToast("需要同意用户服务协议");
			return;
		}

		try {
			// 发送短信验证码请求
			const response = await sendSmsVerificationCode(loginInfo.mobile, 'mobilelogin');
			useShowToast(response.msg);
			// 计算验证码有效截止时间，并将其存储到本地缓存
			const entTime = Date.now() + COUNTDOWN_DURATION;
			uni.setStorageSync(VERIFICATION_CODE_CACHE_TIMESTAMP_KEY.value, String(entTime));

			// 开始倒计时
			countDown(entTime);
		} catch (err) {
			console.error(err);
		}
	};

	/**
	 * 实现倒计时逻辑
	 * @param targetTimestamp 验证码过期时间戳
	 */
	const countDown = (targetTimestamp : number) => {
		if (countdownRuning.value) return;
		countdownRuning.value = true;

		// 定义倒计时内部递归函数
		const tick = () => {
			setTimeout(() => {
				const remainingTime = targetTimestamp - Date.now();
				// 如果剩余时间大于等于0，则更新倒计时并继续递归
				if (remainingTime >= 0) {
					countdownTime.value = remainingTime;
					tick();
				} else {
					// 倒计时结束，重置状态并移除缓存中的时间戳
					countdownRuning.value = false;
					uni.removeStorageSync(VERIFICATION_CODE_CACHE_TIMESTAMP_KEY.value);
					countdownTime.value = COUNTDOWN_DURATION;
				}
			}, 100);
		};

		// 启动倒计时
		tick();
	};

	/**
	 * 检查是否需要继续之前的倒计时
	 */
	const checkCountDown = () => {
		const SOTRE_TIMESTAMP = uni.getStorageSync(VERIFICATION_CODE_CACHE_TIMESTAMP_KEY.value);

		// 如果当前时间小于存储的时间戳，则继续倒计时
		if (typeof SOTRE_TIMESTAMP === 'string' && Date.now() < parseInt(SOTRE_TIMESTAMP)) {
			countDown(parseInt(SOTRE_TIMESTAMP));
		} else {
			// 否则移除已过期的时间戳
			uni.removeStorageSync(VERIFICATION_CODE_CACHE_TIMESTAMP_KEY.value);
		}
	};

	// 用户协议相关变量和函数

	// 用户是否同意协议的引用类型
	const agreementStatus = ref<boolean>(false);
	// 用户协议是否正在震动提示的引用类型
	const agreementShake = ref<boolean>(false);

	// 关闭协议震动提示
	const closeShake = () => {
		agreementShake.value = false;
	};

	// 用户同意或取消协议
	const agreeAgreement = () => {
		agreementStatus.value = !agreementStatus.value;
	};

	// 跳转至用户协议页面
	const jumpAgreement = () => {
		uni.navigateTo({
			url: "/pages/user-agreement/index"
		});
	};

	// 检查手机号输入是否合法
	const checkMobile = () => {
		const phoneNumberRegex = /^(?:1(?:[1-9]\d|\d[3-9])\d{8})$/;

		// 根据手机号合法性显示相应提示并返回检查结果
		if (loginInfo.mobile === '') {
			useShowToast("手机号不能为空");
			return false;
		}
		if (!phoneNumberRegex.test(loginInfo.mobile)) {
			useShowToast("请输入正确的手机号");
			return false;
		}
		return true;
	};

	// 用户登录逻辑
	const userLogin = async () => {
		if (!checkMobile()) {
			return;
		}
		if (loginInfo.captcha.length === 0) {
			useShowToast("验证码不能为空");
			return;
		} else if (loginInfo.captcha.length < 6) {
			useShowToast("验证码错误");
			return;
		}

		// 检查用户是否同意服务协议
		if (!agreementStatus.value) {
			agreementShake.value = true;
			useShowToast("需要同意用户服务协议");
		} else {
			try {
				// 登录请求
				const response = await apiMobilelogin(loginInfo.mobile, loginInfo.captcha);
				console.log(response)
				uni.setStorageSync('userInfo', {
					username: response.userinfo.username,
					user_id: response.userinfo.user_id,
					nickname: response.userinfo.nickname,
					avatar: response.userinfo.avatar,
					mobile: response.userinfo.mobile
				})
				// 存储登录后的token到本地缓存，并跳转至首页
				uni.setStorageSync('token', response.userinfo.token);
				uni.switchTab({
					url: "/pages/index/index"
				});
			} catch (err) {
				console.error(err);
			}
		}
	};

	// 页面显示时触发的回调函数
	onShow(() => {
		checkCountDown();
		console.log('展示Login页面', Date.now());
	});

	// 页面隐藏时触发的回调函数
	onHide(() => {
		console.log('页面停止');
	});


	/**
	 * 返回拦截，用户必须保存他的曲谱
	 */
	onBackPress(() => {
		const token : string | null = uni.getStorageSync('token');
		if (token) {
			return false
		} else {
			return true
		}
	})

</script>

<style lang="scss">
	/* 水平抖动 */
	@keyframes shake {

		10%,
		90% {
			transform: translate3d(-1px, 0, 0);
		}

		20%,
		80% {
			transform: translate3d(+2px, 0, 0);
		}

		30%,
		70% {
			transform: translate3d(-4px, 0, 0);
		}

		40%,
		60% {
			transform: translate3d(+4px, 0, 0);
		}

		50% {
			transform: translate3d(-4px, 0, 0);
		}
	}

	.agreementShake {
		animation: shake 800ms ease-in-out;
	}

	.app-logo {
		padding: 60rpx 250rpx 32rpx 250rpx;
		display: flex;
		align-items: center;

		image {
			border-radius: 50%;
			overflow: hidden;
			width: 250rpx;
			height: 250rpx;
		}
	}

	.app-login {
		display: flex;
		flex-direction: column;
		width: 750rpx;

		.app-login-form-item {
			padding: 48rpx 58rpx 0 62rpx;

			.app-login-form-item-label {
				display: flex;
				align-items: center;

				.app-login-form-item-label-icon {
					width: 36rpx;
					height: 36rpx;
				}

				.app-login-form-item-label-text {
					font-size: 28rpx;
					margin-left: 10rpx;
				}
			}

			.app-login-form-input {
				height: 40rpx;
				font-size: 28rpx;
				padding: 50rpx 0 12rpx 0;
				border-bottom: 2rpx solid #666666;
				display: flex;
				align-items: center;
				justify-content: space-between;
			}

			.send-verification {
				color: #25DADA;
			}
		}

		.user-agreement {
			display: flex;
			align-items: center;
			font-size: 24rpx;
			color: #8A8A8A;
			padding: 48rpx 60rpx 0 60rpx;
			width: 100%;

			.radio {
				width: 24rpx;
				height: 24rpx;
				border-radius: 50%;
				border: 1rpx solid #8A8A8A;
				// box-sizing: border-box;
				z-index: 1;
				margin-right: 10rpx;

				// position:relative;
				.radio-img {
					z-index: 1;
					position: absolute;
					// margin: auto;
					width: 24rpx;
					height: 24rpx;
				}
			}

			.agreement {
				color: #25DADA;
			}
		}

		.submit-button {
			width: 630rpx;
			height: 80rpx;
			background-color: #25DADA;
			border-radius: 80rpx;
			margin: 0 auto;
			margin-top: 32rpx;
			line-height: 80rpx;
			color: $uni-text-color;

		}
	}
</style>